home *** CD-ROM | disk | FTP | other *** search
- /*--------------------------------------------------------------*/
- /* ANIMDAT 1.1 */
- /* copyright 1992 - TODD SANKEY */
- /* */
- /* The author hereby grants permission for the use and sharing */
- /* of both source code end executable versions of this software */
- /* at no charge. This software is not for sale and no other */
- /* shall charge for it without the expressed consent of the */
- /* author. */
- /* */
- /* The source code can be freely modified, but it must retain */
- /* the original copyright notice, and the author must be */
- /* notified of these changes if the altered code is to be */
- /* distributed. */
- /*--------------------------------------------------------------*/
- /*------------------------------------------------------*/
- /* scanner.c Scans and tokenizes a source buffer. */
- /*------------------------------------------------------*/
-
- #define scanner_c
-
- #include <ctype.h>
- #include <string.h>
- #include <stdio.h>
- #include "common.h"
-
- #define MAX_LINE_LENGTH 256
- #define EOB_CHAR 0
- #define SPECIAL 1
- #define LETTER 2
- #define DIGIT 3
-
- /* globals */
- TOKEN_CODE token;
- char word_string[MAX_LINE_LENGTH];
- double literal_value;
- char *token_names[]={"No token","Identifier","Number","String","^","*",
- "(",")","-","+","=","<",">","<=",">=","<>","/",",",
- "OR","AND","SIN","COS","TAN","EXP","LOG","RND","ATAN",
- "ASIN","ACOS","#","quote",
- "ERROR","NUMSCENE","%","END OF BUFFER"};
-
- /* variable used inside scanner module */
- static int ch; /* current input character from source buffer */
- static char *buffer_offset; /* offset into source buffer */
- static char *bufferp; /* start of source buffer */
- static char token_string[MAX_LINE_LENGTH];
- static char *tokenp = token_string;
- static int digit_count;
- static char char_table[256];
-
- static char rw_2[]={'o','r',OR,0};
- static char rw_3[]={'a','n','d',AND,
- 's','i','n',SIN,
- 'c','o','s',COS,
- 't','a','n',TAN,
- 'e','x','p',EXP,
- 'l','o','g',LOG,
- 'r','n','d',RND,0};
- static char rw_4[]={'a','t','a','n',ATAN,
- 'a','s','i','n',ASIN,
- 'a','c','o','s',ACOS,0};
- static char rw_10[]={'n','u','m','_','s','c','e','n','e','s',NUMSCENE,0};
-
- static char *rsvd_word_table[] = { NULL, NULL, rw_2, rw_3, rw_4,NULL,NULL,NULL,NULL,NULL, rw_10 };
- #define MAX_RESERVED_WORD_LENGTH 10
- #define MIN_RESERVED_WORD_LENGTH 2
-
-
- /* Local procedures */
- void get_char();
- void skip_comment();
- void skip_blanks();
- void get_word();
- void get_number();
- void get_special();
- void downshift_word();
- int is_reserved_word();
-
-
- #define char_code(ch) char_table[ch]
-
-
- /********************************/
- /* */
- /* Initialization routines */
- /* */
- /********************************/
-
-
- /*----------------------------------------------------------------------*/
- /* init_scanner Initialize the scanner globals and start the */
- /* scanner at the specified point. */
- /*----------------------------------------------------------------------*/
-
- void init_scanner(char *source_buffer)
- {
- ch = 0;
- token = NO_TOKEN;
- word_string[0] = 0;
- literal_value = 0.0;
- token_string[0] = 0;
- tokenp = token_string;
- digit_count = 0;
- bufferp = source_buffer;
- buffer_offset = bufferp;
-
- for (ch = 0; ch<256; ch++) char_table[ch] = SPECIAL;
- for (ch = '0'; ch <='9'; ch++) char_table[ch] = DIGIT;
- for (ch = 'a'; ch <='z'; ch++) char_table[ch] = LETTER;
- for (ch = 'A'; ch <='Z'; ch++) char_table[ch] = LETTER;
- char_table[0] = EOB_CHAR;
-
- get_char(); /* Get first character of source buffer */
- get_token(); /* initialize to first token in buffer */
- }
-
-
-
- /********************************/
- /* */
- /* Character routines */
- /* */
- /********************************/
-
- /*----------------------------------------------------------------------*/
- /* get_char Set ch to the next character from the source */
- /* buffer. */
- /*----------------------------------------------------------------------*/
-
- void get_char()
- {
- ch = *buffer_offset++;
- switch (ch) {
- case '\0' :
- buffer_offset--;
- break;
- case '\t' : /* Make tab and new-line characters */
- case '\n' : /* appear as spaces. */
- ch = ' ';
- break;
-
- case '{' : /* Ignore comment and make it appear */
- skip_comment(); /* as a space. */
- ch = ' ';
- break;
- }
- }
-
-
- /*----------------------------------------------------------------------*/
- /* skip_comment Skip over a comment. Set ch to '}' */
- /*----------------------------------------------------------------------*/
-
- void skip_comment()
- {
- do {
- get_char();
- } while ( (ch != '}') && (ch != EOB_CHAR) );
- }
-
-
- /*----------------------------------------------------------------------*/
- /* skip_blanks Skip over white space */
- /*----------------------------------------------------------------------*/
-
- void skip_blanks()
- {
- while (ch == ' ') get_char();
- }
-
-
-
- /********************************/
- /* */
- /* Token routines */
- /* */
- /********************************/
- /* Note: after a token has been extracted, ch is the first character after
- the token. */
-
- /*----------------------------------------------------------------------*/
- /* get_token Extract the next token from the source buffer. */
- /*----------------------------------------------------------------------*/
-
- void get_token()
- {
- skip_blanks();
- tokenp = token_string;
-
- switch (char_code(ch)) {
- case LETTER: get_word(); break;
- case DIGIT: get_number(); break;
- case EOB_CHAR: token = END_OF_FILE; break;
- default: get_special(); break;
- }
- }
-
-
- /*----------------------------------------------------------------------*/
- /* get_word Extract a word token and downshift its */
- /* characters. Check if its a reserved word. Set */
- /* token to IDENTIFIER if it's not. */
- /*----------------------------------------------------------------------*/
-
- void get_word()
- {
- while ( (char_code(ch) == LETTER) || (char_code(ch) == DIGIT)
- || (ch == '_') || (ch == '.') ) {
- *tokenp++ = ch;
- get_char();
- }
- *tokenp = '\0';
- downshift_word();
- if (!is_reserved_word() )
- token = IDENTIFIER;
- }
-
-
- /*----------------------------------------------------------------------*/
- /* get_number Extract a number token and set literal_value to */
- /* its value. Set token to NUMBER. */
- /*----------------------------------------------------------------------*/
-
- void get_number()
- {
- double real_part = 0.0, temp_real, tenths;
- long whole_part = 0;
-
- /* Accumulate whole number part */
- while ( char_code(ch) == DIGIT) {
- whole_part = (10*whole_part) + (ch - '0');
- *tokenp++ = ch;
- get_char();
- }
-
- if (ch == '.') {
- tenths = 10.0;
- *tokenp++ = ch;
- get_char();
- while ( char_code(ch) == DIGIT) {
- temp_real = (double)(ch - '0');
- temp_real /= tenths;
- real_part+= temp_real;
- tenths *= 10.0;
- *tokenp++ = ch;
- get_char();
- }
- }
-
- *tokenp = '\0';
- real_part += (double)whole_part;
- token = NUMBER;
- literal_value = real_part;
- }
-
-
-
- /*----------------------------------------------------------------------*/
- /* get_quote Extract the literal contents between two */
- /* quotation marks. */
- /*----------------------------------------------------------------------*/
-
- void get_quote()
- {
- int count;
-
- ch = *buffer_offset++;
- for (count=0 ; (count < MAX_LINE_LENGTH) && (ch != '"'); count++) {
- word_string[count] = ch;
- ch = *buffer_offset++;
- }
- if (count >= MAX_LINE_LENGTH)
- error(LINE_TOO_LONG,cur_line);
-
- word_string[count] = '\0';
- get_char();
- }
-
-
- /*----------------------------------------------------------------------*/
- /* get_special Extract a special token. Some are single */
- /* character and some are double. Set token */
- /* appropriately. */
- /*----------------------------------------------------------------------*/
-
- void get_special()
- {
- *tokenp++ = ch;
- switch (ch) {
- case '^': token = CARET; get_char(); break;
- case '*': token = STAR; get_char(); break;
- case '(': token = LPAREN; get_char(); break;
- case ')': token = RPAREN; get_char(); break;
- case '-': token = MINUS; get_char(); break;
- case '+': token = PLUS; get_char(); break;
- case '/': token = SLASH; get_char(); break;
- case '=': token = EQUAL; get_char(); break;
- case ',': token = COMMA; get_char(); break;
- case '#': token = POUND; get_char(); break;
- case '"': token = QUOTE; get_quote(); break;
- case '%': token = PERCENT; get_char(); break;
- case '<': get_char();
- if (ch == '=') { /* <= */
- *tokenp++ = ch;
- token = LE;
- get_char();
- }
- else if (ch == '>') { /* <> */
- *tokenp++ = ch;
- token = NE;
- get_char();
- }
- else
- token = LT;
- break;
-
- case '>': get_char();
- if (ch == '=') { /* >= */
- *tokenp++ = ch;
- token = GE;
- get_char();
- }
- else
- token = GT;
- break;
-
- case '!': get_char();
- if (ch == '=') {
- *tokenp++ = ch;
- token = NE;
- get_char();
- }
- else
- token = ERROR;
- break;
-
- default: token = ERROR;
- get_char();
- break;
- }
- *tokenp = '\0';
- }
-
-
- /*----------------------------------------------------------------------*/
- /* downshift_word Copy a word token into word_string with all */
- /* characters converted to lower case. */
- /*----------------------------------------------------------------------*/
-
- void downshift_word()
- {
- char *wp = word_string;
- char *tp = token_string;
-
- do {
- *wp++ = (*tp++);
- } while ( (*tp) != '\0' );
- *wp = '\0';
- }
-
-
- /*----------------------------------------------------------------------*/
- /* is_reserved_word Checks if a word token is a reserved word. If */
- /* so, set token appropriately and return 1. */
- /* Otherwise return 0. */
- /*----------------------------------------------------------------------*/
-
- int is_reserved_word()
- {
- int word_length;
- char *rwp;
-
- word_length = strlen(word_string);
- if (word_length >= MIN_RESERVED_WORD_LENGTH && word_length <= MAX_RESERVED_WORD_LENGTH) {
- for (rwp = rsvd_word_table[word_length];
- (rwp != NULL) && (*rwp != '\0') ;
- rwp += (word_length+1) ) {
- if (!strncmp(word_string,rwp,word_length) ) {
- token=(TOKEN_CODE)( *(rwp+word_length));
- return (1);
- }
- }
- }
- return (0);
- }
-